package com.pai4j.aigc.llm;
import com.pai4j.aigc.context.ContextKit;
import com.pai4j.aigc.service.PlantUmlService;
import com.pai4j.aigc.service.BotService;
import com.pai4j.common.constants.ConnectConstants;
import com.pai4j.common.enums.AiFunctionEnum;
import com.pai4j.common.enums.MessageTypeEnum;
import com.pai4j.common.enums.OutputFormat;
import com.pai4j.common.enums.messagequeue.MessageQueueEnum;
import com.pai4j.common.helper.SseEmitterHelper;
import com.pai4j.common.service.messagequeue.producer.MessageQueueProducer;
import com.pai4j.common.util.JsonUtil;
import com.pai4j.domain.dto.aigc.RenderResult;
import com.pai4j.domain.dto.bot.BotDTO;
import com.pai4j.domain.vo.llm.FunctionCallResponse;
import com.pai4j.domain.vo.llm.image.ImageGenerateResponse;
import com.pai4j.domain.vo.llm.image.RequestGenerateBaseParam;
import com.pai4j.domain.vo.llm.image.RequestGenerateParam;
import com.pai4j.domain.vo.request.request.mess.ChatMessageRequestVO;
import com.pai4j.domain.vo.response.UploadResultVO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AiAgentFlowService {

    @Autowired
    private GPTChatService gptChatService;
    @Autowired
    private AiFunctionCallService aiFunctionCallService;
    @Autowired
    private LibLibGenerateImageService libLibGenerateImageService;
    @Autowired
    private AiBotPluginService aiBotPluginService;
    @Autowired
    private BotService botService;
    @Resource
    private PlantUmlService plantUmlService;


    @Autowired
    private MessageQueueProducer<ChatMessageRequestVO, Long> messageQueueProducer;

    /**
     * 旗舰版文生图模版id
     */
    private static final String TEMPLATE_UUID = "5d7e67009b344550bc1aa6ccbfa1d7f4";



    private String getSSEBizCode() {
        return ConnectConstants.ConnectBiz.getBizCode(ConnectConstants.ClientEnum.PC,
                                                      ConnectConstants.AppEnum.WEB,
                                                      ConnectConstants.BizEnum.CHAT);
    }

    /**
     * 机器人问答Agent服务
     * 1、意图识别
     * 2、文生文（kimi/deepseek） / 文生图（LibLib模型）
     *
     * @param messageJson
     */
    public void doAgent(String messageJson) {
        // 清理可能的双引号包装
        String cleanedJson = messageJson;
        if (messageJson.startsWith("\"") && messageJson.endsWith("\"")) {
            cleanedJson = messageJson.substring(1, messageJson.length() - 1);
            // 处理转义字符
            cleanedJson = cleanedJson.replace("\\\"", "\"");
        }

        ChatMessageRequestVO chatMessage = JsonUtil.fromJson(cleanedJson, ChatMessageRequestVO.class);

        if (!SseEmitterHelper.isExist(getSSEBizCode(), chatMessage.getSenderId())) {
            /**
             * 因为当前doAgent AIGC服务消费来自pai4j-connect服务的websocket端点的MQ广播消息
             * 所以，在分布式部署场景下，可能当前消息发送人的sse链接并不在当前节点。
             */
            return;
        }

        /**
         * 消息持久化用户发给机器人消息
         */
        this.persistentAiMessage(chatMessage.getSenderId(), chatMessage.getReceiverId(), chatMessage.getMessage());
        // 上下文：确认/创建会话（优先使用请求中的 sessionId，避免复用上一活跃会话）。
        // 注意：此处不立刻写入用户消息，避免 CHAT 流程在 GPTChatService 中再次写入导致重复。
        String sessionId = ContextKit.ensureSession(chatMessage.getSenderId(), chatMessage.getReceiverId(), chatMessage.getSessionId());

        String senderId = chatMessage.getSenderId();
        /**
         * 1. 意图识别
         */
        SseEmitterHelper.send(this.getSSEBizCode(), senderId, "意图识别中...");
        FunctionCallResponse functionCallResponse;
        String function = null;
        AiFunctionEnum aiFunctionEnum = null;
        
        try {
            // 汇总已发布插件供意图识别
            List<String> pluginList = new ArrayList<>();
            List<BotDTO> botDTOList = botService.getPublishBotDetailFromCache();
            if (CollectionUtils.isNotEmpty(botDTOList)) {
                pluginList = botDTOList.stream()
                        .map(bot -> bot.getCode().concat(":").concat(bot.getDescription()))
                        .collect(Collectors.toList());
            } else {
                pluginList.add("");
            }
            Map<String, Object> vars = new HashMap<>();
            vars.put("input", chatMessage.getMessage());
            vars.put("pluginFuncList", pluginList);

            functionCallResponse = aiFunctionCallService.getFunction(vars,senderId);
            function = functionCallResponse.getFunction();
            // 解析内置意图或插件意图的名称用于提示
            String funcName = "未识别到意图";
            try {
                aiFunctionEnum = AiFunctionEnum.valueOf(function);
                funcName = aiFunctionEnum.getFunctionName();
            } catch (Exception ignore) {
                BotDTO botDTO = botService.getBotPluginFromCache(function);
                if (botDTO != null) {
                    funcName = botDTO.getName();
                }
            }
            log.info("意图识别结果 =====> input: {}, response:{}", chatMessage.getMessage(), JsonUtil.toJsonString(functionCallResponse));
            String functionInfo = "意图识别：" + funcName;
            SseEmitterHelper.send(this.getSSEBizCode(), senderId, functionInfo);
        } catch (Exception e) {
            log.error("意图识别异常 =====> input: {}", chatMessage.getMessage(), e);
            SseEmitterHelper.send(this.getSSEBizCode(), senderId, "意图识别失败，稍后重试～");
            return;
        }
        /**
         * 2. 根据意图执行对应工作流
         */
        SseEmitter sseEmitter = SseEmitterHelper.get(this.getSSEBizCode(), senderId);
        String agentResponse = null;
        // 标记是否在子流程中已经写入了助手回复
        boolean appendedByChild = false;
        // 对于非 CHAT 流程，这里补写一次用户消息到上下文，避免遗漏。
        if (aiFunctionEnum != AiFunctionEnum.CHAT) {
            ContextKit.appendUser(sessionId, chatMessage.getMessage());
        }

        if (aiFunctionEnum == AiFunctionEnum.CHAT) {
            // 机器人对话（gptChatService 内部已写入上下文：用户输入 + 助手回复）
            agentResponse = gptChatService.chat(sseEmitter, chatMessage);
            appendedByChild = true;
        } else if (aiFunctionEnum == AiFunctionEnum.IMAGE ) {
            // 机器人对话
            RequestGenerateBaseParam baseParam = RequestGenerateBaseParam.of(chatMessage.getMessage());
            RequestGenerateParam param = RequestGenerateParam.of(TEMPLATE_UUID, baseParam);
            try {
                ImageGenerateResponse response = libLibGenerateImageService.generate(senderId, param);
                List<String> images = response.getImages();
                if (CollectionUtils.isEmpty(images)) {
                    SseEmitterHelper.send(this.getSSEBizCode(), senderId, "图片生成失败～");
                    return;
                }
                String imageMd = " ![%s](%s \"%s\")";
                StringBuilder stringBuilder = new StringBuilder();
                for (int i = 0; i < images.size(); i++) {
                    String imageName = "图片" + (i + 1);
                    stringBuilder.append(String.format(imageMd, imageName, images.get(i), imageName));
                    if (i == images.size() - 1) {
                        stringBuilder.append("\n");
                    }
                }
                agentResponse = stringBuilder.toString();
                SseEmitterHelper.send(this.getSSEBizCode(), senderId, agentResponse);
            } catch (Exception e) {
                log.error("文生图服务异常 =====> param: {}", JsonUtil.toJsonString(param), e);
                SseEmitterHelper.send(this.getSSEBizCode(), senderId, "文生图服务异常，稍后重试～");
            }
        } else if (aiFunctionEnum == AiFunctionEnum.PLANTUML) {
            try {
                SseEmitterHelper.send(this.getSSEBizCode(), senderId, "UML生成与渲染中...");
                // 1) 生成并优化+渲染为SVG
               RenderResult renderResult = plantUmlService.generateAndRenderFromPrompt(
                        chatMessage.getMessage(),
                        OutputFormat.SVG,
                        true
                );

                // 2) 上传到MinIO，返回URL
                UploadResultVO uploadResult = plantUmlService.saveUmlImage(renderResult, chatMessage.getMessage(), senderId);
                if (uploadResult == null) {
                    SseEmitterHelper.send(this.getSSEBizCode(), senderId, "UML图上传失败～");
                    return;
                }

                String imageUrl = uploadResult.getUrl();
                String svgMd = String.format("![UML](%s \"UML\")", imageUrl);
                agentResponse = svgMd;
                // 3) 流式下发：先下发代码，再下发图片链接
                SseEmitterHelper.send(this.getSSEBizCode(), senderId, "PlantUML代码已生成，开始上传图片...");
                SseEmitterHelper.send(this.getSSEBizCode(), senderId, "```plantuml\n" + renderResult.getPlantUmlCode() + "\n```");
                SseEmitterHelper.send(this.getSSEBizCode(), senderId, "UML图已生成：\n" + svgMd);
            } catch (Exception e) {
                log.error("UML生成流程异常 =====> input: {}", chatMessage.getMessage(), e);
                SseEmitterHelper.send(this.getSSEBizCode(), senderId, "UML生成失败，稍后重试～");
            }
        } else {
            // 插件类处理：参数抽取 + 插件调用 + 大模型增强
            try {
                agentResponse = aiBotPluginService.doChat(chatMessage, this.getSSEBizCode(), function);
            } catch (Exception ex) {
                log.error("插件工作流执行异常 =====> function: {}, input: {}", function, chatMessage.getMessage(), ex);
                SseEmitterHelper.send(this.getSSEBizCode(), senderId, "插件工作流执行异常，稍后重试～");
            }
        }

        /**
         * 机器人响应消息持久化 + 记录上下文
         */
        if (agentResponse != null) {
            this.persistentAiMessage(chatMessage.getReceiverId(), chatMessage.getSenderId(), agentResponse);
            // 如果在子流程中未写入上下文，这里再补写一次助手回复，避免重复
            if (!appendedByChild) {
                ContextKit.appendAssistant(sessionId, agentResponse);
            }
        }
    }


    /**
     * 机器人对话场景，消息持久化
     *
     * @param senderId
     * @param receiverId
     * @param message
     */
    private void persistentAiMessage(String senderId, String receiverId, String message) {
        ChatMessageRequestVO chatMessageRequestVO = new ChatMessageRequestVO();
        chatMessageRequestVO.setSenderId(senderId);
        chatMessageRequestVO.setReceiverId(receiverId);
        chatMessageRequestVO.setMessage(message);
        chatMessageRequestVO.setType(MessageTypeEnum.CHAT_TEXT.getType());
        messageQueueProducer.send(MessageQueueEnum.QUEUE_PERSISTENT_CHAT_MESSAGE, chatMessageRequestVO);
    }
}
